#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author:liang futing
#@Time :2019/4/19 11:41
import re
import json
from django.views.generic import View,UpdateView,CreateView
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from django.shortcuts import Http404
from django.db.models.query import QuerySet
from django.core.exceptions import ImproperlyConfigured
from apps.system.mixin import LoginRequiredMixin
from system.models import Menu

class BreadcrumbMixin:
    def get_context_data(self,**kwargs):
        menu=Menu.get_menu_by_request_url(url=self.request.path_info)
        if menu is not None:
            kwargs.update(menu)
        return super().get_context_data(**kwargs)


class SandboxGetObjectMinix:
    def get_object(self,queryset=None):
        if queryset is None:
            queryset=self.get_queryset()
        if 'id' in self.request.GET and self.request.GET['id']:
            queryset=queryset.filter(id=int(self.request.GET['id']))
        elif 'id' in self.request.POST and self.request.POST['id']:
            queryset=queryset.filter(id=int(self.request.POST['id']))
        else:
            raise AttributeError("Generic dtail view %s must be called with id" %
                                 self.__class__.__name__)
        try:
            obj=queryset.get()
        except queryset.model.DoesNotExist:
            raise Http404("No %(verbose_name)s found matching the query" %
                          {'verbose_name':queryset.model._meta.verbose__name})
        return obj

class SandboxEditMixin:
    def post(self,request,*args,**kwargs):
        res=dict(result=False)
        form=self.get_form()
        if form.is_valid():
            form.save()
            res['result']=True
        else:
            pattern="<li>.*?<ul class=.*?><li>(.*?)</li>"
            form_errors=str(form.errors)
            errors=re.findall(pattern,form_errors)
            res['error']=errors[0]

        return HttpResponse(json.dumps(res),content_type='application/json')

class SandboxCreateView(LoginRequiredMixin,SandboxEditMixin,CreateView):
    '''
    view for create an object,with a response rendered by template.
    returns information with json when the data is creted successfully or fails.
    '''

class SandboxUpdateView(LoginRequiredMixin,SandboxEditMixin,SandboxGetObjectMinix,UpdateView):
    def post(self,request,*args,**kwargs):
        self.object=self.get_object()
        return super().post(request,*args,**kwargs)


class SandboxMultipleObjectMixin:
    filters={}
    fields=[]
    queryset=None
    model=None

    def get_queryset(self):
        if self.queryset is not None:
            queryset=self.queryset
            if isinstance(queryset,QuerySet):
                queryset=queryset.all()
        elif self.model is not None:
            queryset=self.model._default_manager.all()
        else:
            raise ImproperlyConfigured(
                "%(cls)s is missing a QuerySet Define. "
                "%(cls)s .model,%(cls)s.queryset."%{'cls':self.__cls__.__name__}
            )
        return queryset

    def get_datatables_paginator(self,request):
        datatables=request.GET
        draw=int(datatables.get('draw'))
        start=int(datatables.get('start'))
        length=int(datatables.get('length'))
        order_column=datatables.get('order[0][column]')
        order_dir=datatables.get('order[0][dir]')
        order_field=datatables.get('columns[{}][data]'.format(order_column))
        queryset=self.get_queryset()
        if order_dir=='asc':
            queryset=queryset.order_by(order_field)
        else:
            queryset=queryset.order_by('-{0}'.format(order_field))

        record_total_count=queryset.count()
        filters=self.get_filters()#获取过滤字段
        fields=self.get_fields()#获取需要展示的字段
        #
        if filters:
            queryset=queryset.filter(**filters)
        if fields:
            queryset=queryset.values(*fields)

#         过滤后的数据条目
        record_filter_count=queryset.count()
        object_list=queryset[start:(start+length)]
        data=list(object_list)

        return {
            'draw':draw,
            'recordsTotal':record_total_count,
            'recordsFiltered':record_filter_count,
            'data':data,
        }

    def get_filters(self):
        return self.filters

    def get_fields(self):
        return self.fields

class SandboxListView(LoginRequiredMixin,SandboxMultipleObjectMixin,View):
    '''
    jsonreponse some json ob objects,set by 'self.model or self.queryset'

    '''
    def get(self,request):
        context=self.get_datatables_paginator(request)
        return JsonResponse(context)